﻿/**********************************************************************
*创建人：蔡水明
*创建时间：2018/1/19 12:20:53
*说明：<Function>
/**********************************************************************/
using FluentFTP;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Utilities
{
    public class FtpHelper
    {      
        /// <summary>
        /// 错误信息
        /// </summary>
        public string errorMsg = string.Empty;
        public string FtpIP { get; set; }
        public int FtpPort { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        /// <summary>
        /// 远程保存文件夹
        /// </summary>        
        public string RemoteDir { get; set; }
        public List<string> RemoteDirs = new List<string>();
        /// <summary>
        /// 远程文件名称
        /// </summary>
        public string RemoteName { get; set; }
        public List<string> RemoteNames = new List<string>();
        /// <summary>
        /// 本地文件(全路径）
        /// </summary>
        public string LocalFile { get; set; }
        public List<string> LocalFiles = new List<string>();      
        /// <summary>
        /// 要下载的文件
        /// </summary>
        public List<string> TobeDownList { get; set; }
      

        public FtpHelper()
        {

        }       
        /// <summary>
        /// 上传一个文件
        /// </summary>
        /// <param name="localFile"></param>
        /// <param name="remoteFile"></param>
        /// <returns></returns>
        public async Task<bool> UploadAsync(string localFile, string remoteFile, FtpProcess fp)
        {
            bool result = false;
            try
            {               
                var client = new FtpClient { Host = FtpIP, Port = FtpPort, Credentials = new NetworkCredential(UserName, Password) };
                client.Encoding = Encoding.ASCII;
                client.ConnectTimeout = 5000;
                client.ReadTimeout = 15000;
                client.Connect();
                fp.fileName = localFile;
                result =await client.UploadFileAsync(localFile, remoteFile, existsMode: FtpExists.Overwrite,createRemoteDir: true,verifyOptions: FtpVerify.None, token:CancellationToken.None,progress:fp);
                client.Disconnect();
                errorMsg = string.Empty;
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                return false;
            }
            return result;
        }
        /// <summary>
        /// 经过多次使用，效果比较好
        /// </summary>
        /// <returns></returns>
        public bool UploadOverWrite()
        {
            bool result = false;
            errorMsg = string.Empty;
            string curLocalFile = string.Empty;
            int tryTimes = 0;
            int tryConnect = 0;
            bool connectOk = false;
            while (connectOk == false)
            {
                tryConnect++;
                errorMsg = string.Empty;
                try
                {                  
                    var client = new FtpClient { Host = FtpIP, Port = FtpPort, Credentials = new NetworkCredential(UserName, Password) };
                    client.Encoding = Encoding.ASCII;
                    client.ConnectTimeout = 15000;
                    client.ReadTimeout = 15000;
                    client.DataConnectionConnectTimeout = 15000;
                    client.Connect();
                    connectOk = client.IsConnected;
                    for (int i = 0; i < RemoteDirs.Count; i++)
                    {
                        string remoteFile = Path.Combine(RemoteDirs[i], RemoteNames[i]);
                        curLocalFile = LocalFiles[i];
                        result = false;
                        tryTimes = 0;
                        while (result == false)
                        {
                            tryTimes++;
                            try
                            {
                                result = client.UploadFile(curLocalFile, remoteFile, FtpExists.Overwrite, true);
                            }
                            catch (Exception e)
                            {
                                LogHelper.Error($"File:{curLocalFile} 尝试次数：{tryTimes}\r\n");
                                LogHelper.Error(e);
                                Thread.Sleep(1000);
                            }
                            if (tryTimes > 5) break;
                        }
                        if (result == false)
                        {
                            errorMsg = $"上传失败，尝试次数：{tryTimes}";
                            break;
                        }
                    }
                    client.Disconnect();
                }
                catch (Exception ex)
                {
                    LogHelper.Info($"登录错误,尝试次数:{tryConnect}");
                    LogHelper.Error(ex);
                    if (ex.Message.StartsWith("Login"))
                        errorMsg = "登录错误（怀疑是账号或密码)";
                    else
                        errorMsg = "登录错误(怀疑Ftp故障)";
                }
                if (tryConnect > 5) break;
            }
            return result;
        }
        /// <summary>
        /// 异步删除一个文件
        /// </summary>
        /// <param name="remoteFile"></param>
        public void DeleteFileAsyn(string remoteFile)
        {
            try
            {
                var client = new FtpClient { Host = FtpIP, Port = FtpPort, Credentials = new NetworkCredential(UserName, Password) };
                client.Connect();
                client.DeleteFileAsync(remoteFile);                
                errorMsg = string.Empty;
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                LogHelper.Error(ex);
                
            }
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <returns></returns>
        public bool DownLoadFile()
        {
            var client = new FtpClient { Host = FtpIP, Port = FtpPort, Credentials = new NetworkCredential(UserName, Password) };
            client.Connect();

            string remoteFile = Path.Combine(RemoteDir, RemoteName);
            if (!client.FileExists(remoteFile)) return false;
            try
            {
                return client.DownloadFile(LocalFile, remoteFile, true);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                return false;
            }
        }
        /// <summary>
        /// 异步下载文件列表
        /// </summary>
        /// <returns></returns>
        public async Task<int> DownLoadFilesAsync(string Dir, FtpProcess fp)
        {
            var client = new FtpClient { Host = FtpIP, Port = FtpPort, Credentials = new NetworkCredential(UserName, Password) };
            client.Connect();
            int count = 0;
           
            foreach (var item in TobeDownList)
            {
                string tmp = item.TrimStart('/');
                string localFile = Path.Combine(Dir, tmp).Replace("/", "\\");
                fp.fileName = item;
                try
                {
                    if (!client.FileExists(item)) continue;
                    if (await client.DownloadFileAsync(localFile, item, progress: fp))
                    {
                        count++;
                        fp.curIndex = count;
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                    return count;
                }

            }
            return count;
        }
       
    }
}
